package fr.umlv.metadata;

import java.awt.Component;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.ResourceBundle;

import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.text.JTextComponent;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Property;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.enums.PropertyType;
import org.netbeans.spi.wizard.WizardPage;

import fr.umlv.authentication.SessionHandler;

// TODO: Auto-generated Javadoc
/**
 * The Class MetadataPage.
 */
public class MetadataPage extends WizardPage {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;

	/** The lgp. */
	private final ListGenPanel lgp;

	/** The lcp. */
	private final ListCategoryPanel lcp;

	/** The ap. */
	private final AspectPanel ap;

	/** The bundle. */
	private ResourceBundle bundle = ResourceBundle.getBundle("fr.umlv.metadata.MetadataPage",SessionHandler.getLocale());

	/**
	 * Instantiates a new metadata page.
	 *
	 * @param name the name
	 * @param name2 the name2
	 * @param aspectUtils the aspect utils
	 */
	public MetadataPage(String name, String name2,AspectUtils aspectUtils) {

		super(name,name2);

		JPanel panel = new JPanel();
		JTabbedPane tabbedPane;

		tabbedPane=new JTabbedPane();
		lgp = new ListGenPanel(name,bundle);
		lcp = new ListCategoryPanel(name,bundle);
		ap = new AspectPanel(aspectUtils,name,bundle);

		tabbedPane.addTab(bundle.getString("ThumbnailGeneral.text"),lgp);
		tabbedPane.addTab(bundle.getString("ThumbnailCategory.text"),lcp);
		tabbedPane.addTab(bundle.getString("ThumbnailAdvanced.text"),ap);

		panel.add(tabbedPane);
		add(panel);
	}

	/**
	 * Instantiates a new metadata page.
	 *
	 * @param obj the obj
	 * @param aspectUtils the aspect utils
	 */
	public MetadataPage(CmisObject obj,AspectUtils aspectUtils) {
		this(obj.getName(),obj.getName(),aspectUtils);

		if(obj.getProperty("cm:author") != null)
			lgp.getAuthorTextField().setText(obj.getProperty("cm:author").getValueAsString());
		if(obj.getProperty("cm:title") != null)
			lgp.getTitreTextField().setText(obj.getProperty("cm:title").getValueAsString());
		if(obj.getProperty("cm:description") != null)
			lgp.getDescriptionTextArea().setText(obj.getProperty("cm:description").getValueAsString());

		if(obj.getProperty("cm:categories") != null){
			for(Object cat : obj.getProperty("cm:categories").getValues()){
				String categorie = (String) cat;
				lcp.addCategory(categorie);
			}
		}

		//to store aspect with properties
		HashMap<String,List<HashMap<String, Property<?>>>> aspectProperties = new HashMap<String, List<HashMap<String, Property<?>>>>();

		for(Property<?> prop : obj.getProperties()){
			String aspect = aspectUtils.getName(prop.getId());
			if(aspect!=null) {
				if(aspectProperties.containsKey(aspect)) {

					HashMap<String,  Property<?>> mapKV= new HashMap<String,  Property<?>>();
					mapKV.put(prop.getDisplayName(), prop);
					aspectProperties.get(aspect).add(mapKV);
				}else {

					List<HashMap<String,  Property<?>>> keyValueProperty = new ArrayList<HashMap<String, Property<?>>>();
					HashMap<String,  Property<?>> mapKV= new HashMap<String,  Property<?>>();
					mapKV.put(prop.getDisplayName(), prop);
					keyValueProperty.add(mapKV);
					aspectProperties.put(aspect, keyValueProperty);
				}
			}
		}

		//to display aspect with properties
		for (Entry<String,List<HashMap<String,  Property<?>>> > e : aspectProperties.entrySet()) {

			ap.createTab(e.getKey(),e.getValue(),obj);
			//ap.displayTab(e.getKey(), e.getValue());
			/*for (HashMap<String, String> map : e.getValue()) {
				for (Entry<String,String> emap : map.entrySet()) {
				}
			}*/
		}
		int c = ap.getTabbedPane().getTabCount();
		if(c>0) {
			ap.getTabbedPane().setVisible(true);
		}

	}


	//Test
	/**
	 * Instantiates a new metadata page.
	 *
	 * @param name the name
	 * @param name2 the name2
	 * @param aspectUtils the aspect utils
	 * @param bundle2 the bundle2
	 */
	public MetadataPage(String name, String name2, AspectUtils aspectUtils,
			ResourceBundle bundle2) {

		super(name,name2);
		bundle = bundle2;
		JPanel panel = new JPanel();
		JTabbedPane tabbedPane;

		tabbedPane=new JTabbedPane();
		lgp = new ListGenPanel(name,bundle);
		lcp = new ListCategoryPanel(name,bundle);
		ap = new AspectPanel(aspectUtils,name,bundle);

		tabbedPane.addTab(bundle.getString("ThumbnailGeneral.text"),lgp);
		tabbedPane.addTab(bundle.getString("ThumbnailCategory.text"),lcp);
		tabbedPane.addTab(bundle.getString("ThumbnailAdvanced.text"),ap);

		panel.add(tabbedPane);
		add(panel);
	}

	/**
	 * Gets the description.
	 *
	 * @return the description
	 */
	public static final String getDescription ()
	{
		return "Metadata page";
	}

	/* (non-Javadoc)
	 * @see org.netbeans.spi.wizard.WizardPage#validateContents(java.awt.Component, java.lang.Object)
	 */
	protected String validateContents (Component comp, Object o)
	{
		String content = null;

		if (lgp.getTitreTextField().getText ().length () == 0)
			content = bundle.getString("title_missing");
		else
			if (lgp.getAuthorTextField().getText ().length () == 0){
				content = bundle.getString("author_missing");
			}else {


				for(Entry<JTextComponent,PropertyDefinition<?>> entry: ap.getMapToCheckType().entrySet()){

					if(PropertyType.DATETIME.equals(entry.getValue().getPropertyType())){
						content = validateContentsDate(entry.getValue(), entry.getKey().getText());
					}
					else{
						content = validateContentsType(entry.getValue(), entry.getKey().getText());
					}
					if(content != null) return content;
				}
			}

		return content;
	}

	/**
	 * Validate contents type.
	 *
	 * @param pd the pd
	 * @param value the value
	 * @return the string
	 */
	private String validateContentsType(PropertyDefinition<?> pd, String value){

		if(value==null || value.isEmpty()) return null;

		if(!checkValue(pd, value)){
			return MessageFormat.format(bundle.getString("bad_type"),pd.getDisplayName(),pd.getPropertyType());
		}

		return null;
	}

	/**
	 * Validate contents date.
	 *
	 * @param pd the pd
	 * @param value the value
	 * @return the string
	 */
	private String validateContentsDate(PropertyDefinition<?> pd, String value){

		if(value==null || value.isEmpty()) return null;

		if(!checkValue(pd, value)){
			return MessageFormat.format(bundle.getString("bad_date"),pd.getDisplayName());
		}

		return null;
	}

	/**
	 * Check value.
	 *
	 * @param type the type
	 * @param value the value
	 * @return true, if successful
	 */
	private boolean checkValue(PropertyDefinition<?> type,String value){

		switch (type.getPropertyType()) {

		case INTEGER:

			try{
				Integer.parseInt(value);
				return true;
			}
			catch (NumberFormatException e) {
				return false;
			}

		case DECIMAL:

			try{
				Double.parseDouble(value);
				return true;
			}
			catch (Exception e) {
				return false;
			}

		case BOOLEAN:

			return true;

		case DATETIME:

			try {
				SessionHandler.getDateFormat().parse(value);
				return true;

			} catch (ParseException e1) {
				return false;
			}

		case STRING:
		case HTML:
		
			return true;
			
		case ID:

			//TODO
			return false;
		}

		return false;
	}


}
